package com.ly.demo.classdemo;

/**
 * @author liuyang
 * @des Java程序在运行时，系统一直对所有的对象进行运行时类型标识，这项信息记录了每个对象所属的类。
 * JVM通常使用运行时类型信息定位正确方法去执行，用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态，当装载类时，Class类型的对象自动创建。
 * <p>
 * JVM为每种类型管理一个独一无二的Class对像，即每个类（型）都有一个Class对象。
 * 运行程序时，JVM首先检查所要加载的类对应的Class对象是否已经加载，如果没有加载，JVM就会根据类名查找.class文件，并将其Class对象载入。
 * <p>
 * Class无公共构造方法，其对象是在加载类时由JVM以及通过调用类加载器中的defineClass方法自动构造的，因此不能显示地声明一个Class对象。
 * 每个类都有一个class属性，可以直接以类.class方式访问，也可以通过实例访问，但实例获得class对象必须要调用getClass()方法才可以。
 * Class类的方法
 * 　　static Class forName(String name)————返回指定类名的Class对象（注意静态的）
 * 　　Object newInstance()————调用缺省构造方法，返回该Class对象的一个实例
 * 　　getName()————返回此Class对象所表示的实体（类、接口、数组、基本类型或void）名称
 * 　　Class []getInstance————获取当前Class对象的接口
 * 　　ClassLoader getClassLoader()————返回该类的加载器
 * 　　Class getSuperclass()————返回表示此Class所表示的实体的超类的Class
 * @Version 1.0
 * @Date: 05/08/2021 09:35
 */

public class ClassDemo {

    /**
     * 演示Class类
     *
     * @param args
     */
    public static void main(String[] args) {
        String className = "com.ly.demo.classdemo.Student";
        //因为调用forName()方法可能抛出异常，需要放到try中
        try {
            //调用静态方法forName()获取字符串对应的Class对象
            Class c1 = Class.forName(className);
            //构造一个对象，但是相应的构造类中必须提供缺省的构造函数,才能使用Class类的缺省构造方法
            Object obj = c1.newInstance();
            System.out.println(obj.toString());
            System.out.println(obj.getClass());
            //通过类.class,获取Class实例
            System.out.println(Student.class);
            //通过具体对象，获取Class实例，但具体对象获取Class实例必须调用getClass()方法
            System.out.println(obj.getClass().getName());
            //判断类.class 与  具体对象获取Class实例是否是统一引用地址
            if (obj.getClass() == Student.class) {
                System.out.println("The Class is Student class！");
                //JVM为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。
                // 通过运行结果分析，可以确定obj.getClass()和Student.class事实上是JVM管理的同一个Class对象。
            }
            System.out.println("----------------");

            //获取当前Class对象的父类Class对象
            Class superClass = c1.getSuperclass();
            Object obj2 = superClass.newInstance();
            System.out.println(obj2.getClass().getName());

            //继续获取父类的Class对象
            Class furtherClass = superClass.getSuperclass();
            Object obj3 = furtherClass.newInstance();
            System.out.println(obj3.getClass().getName());

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
